//
//  TimeLine
//
//  Created by Ryan Mark on 2008-08-12.
//  Copyright (c) 2008 Ryan Mark. All rights reserved.
//
import com.ryanmark.*;
import mx.transitions.easing.*;
import mx.transitions.Tween;

class com.ryanmark.TimeLine
extends MovieClip
{
  private var __height:Number=100;
  private var __width:Number=850;
  private var __draggable:Boolean=false;
  
  //for mouse clicking and dragging
  private var __mouseDealy_mc:MovieClip;
  private var __mouseStartPosition:Number=0;
  private var __moving:Boolean=false;
  private var __mouseXVelocityLastPosition:Number=0;
  private var __mouseXVelocity:Number=0;
  private var __mouseTimer:Number=0;
  
  //vars for what date range will appear, and max and min date range
  private var __selectedDate:TLDate;
  private var __viewRangeStart:TLDate;
  private var __viewRangeEnd:TLDate;
  
  private var __lineRangeStart:TLDate;
  private var __lineRangeEnd:TLDate;
  
  //vars for pixel position of the entire timeline (__positionMin is always zero)
  private var __position:Number;
  private var __positionMin:Number = 0;
  private var __positionMax:Number;
  
  private var __mainTimeLine_mc:MovieClip;
  private var __mainTimeLineMask_mc:MovieClip;
  
  private var __intervalWidth:Number=80;
  
  //pushpins
  private var __pushPins_array:Array = new Array();
  
  //styles
  private var __yearFmt:TextFormat;
  private var __monthFmt:TextFormat;
  
  private var __yearMC_array:Array;
  
  private static var __monthNames_array:Array = new Array("jan.", "feb.", "mar.", "apr.", "may", "jun.", "jul.", "aug.", "sep.", "oct.", "nov.", "dec.");

  public static var symbolName:String = '__Packages.com.ryanmark.TimeLine';
  public static var symbolOwner:Function = TimeLine;
  public static var symbolLink:Boolean = Object.registerClass(symbolName, symbolOwner);
  
	function TimeLine(){
    __selectedDate = new TLDate(2008,4,13);
    __viewRangeStart = new TLDate(2007,5,1);
    __viewRangeEnd = new TLDate();

    __lineRangeStart = new TLDate(2004,1,1);
    __lineRangeEnd = new TLDate();
    
    __mainTimeLineMask_mc = _parent;
    __width = _parent._width;
    __height = _parent._height;

	  //styles
    __yearFmt = new TextFormat();
    __yearFmt.color = 0x7a7a7a;
    __yearFmt.font = "Arial";
    __yearFmt.kerning = true;
    __yearFmt.size = 68;
    __yearFmt.letterSpacing = -7;
    
    __monthFmt = new TextFormat();
    __monthFmt.color = 0xb8b8b8;
    __monthFmt.font = "Arial";
    __monthFmt.kerning = true;
    __monthFmt.size = 28;
    __monthFmt.letterSpacing = -2;
    
    //setup mesurements for the timeline
	  var monInt:Number = __viewRangeStart.compareMonth(__viewRangeEnd);
	  __intervalWidth = Math.round(__width/monInt);
	  
	  __positionMax = __lineRangeStart.compareMonth(__lineRangeEnd)*__intervalWidth;
	  
	  //hitArea=_parent;

    //create dealy to handle mouse events
    __mouseDealy_mc = createEmptyMovieClip('__mouseDealy_mc',2);
    __mouseDealy_mc.hitArea = _parent;
    __mouseDealy_mc.onPress = function():Void {
      _parent.moving=true;
      _parent.mouseStartPosition = _xmouse;
    }
    __mouseDealy_mc.onRelease = function():Void {
      //FIX: does not stop on release outside of MC
      _parent.moving=false;
    }
    __mouseDealy_mc.onMouseMove = function():Void {
      if(_parent.moving) {
    	  //trace(__position+"+("+_xmouse+"-"+__mouseStartPosition+")");
        _parent.move(_parent.position-(_parent._xmouse-_parent.mouseStartPosition));
    	  _parent.mouseStartPosition = _parent._xmouse;
    	}
    }
    
		draw();
	}
	
	function draw():Void
	{
	  //set current pixel position
	  __position = __lineRangeStart.compareMonth(__viewRangeStart)*__intervalWidth;
	  //trace("after draw: "+__position);
	  
	  //clear and setup main part of the timeline
	  __mainTimeLine_mc.removeMovieClip();
	  __mainTimeLine_mc = createEmptyMovieClip('__mainTimeLine_mc', 1);
	  //__mainTimeLine_mc.setMask(__mainTimeLine_mcMask);

    //clear pushpins parent reference
    for ( var i in __pushPins_array ) {
	    __pushPins_array[i].virtualParent=null;
	  }
	  
	  //weird independent coords for MCs not sure if this fixes stuff
	  var tmpObj:Object = {x:(_parent._x+_parent._width),y:(_parent._y+_parent._height)};
	  __mainTimeLine_mc.globalToLocal(tmpObj);
	  
	  var cnt:Number=0;
	  var tmp_metrics_obj:Object;
	  var curPos:TLDate = new TLDate(__viewRangeStart.getTime());
	  var endPos:TLDate = new TLDate(__viewRangeEnd.getTime());
	  endPos.advanceMonth(1);
	  
	  __yearMC_array = new Array();
	  
	  //loop through the months
	  while(curPos.getTime()<=endPos.getTime())
	  {
	    //draw year if its the beginning of the view or if it's a new year
	    if(curPos.getTime() == __viewRangeStart.getTime() || curPos.getMonth()==0) {
        tmp_metrics_obj = __yearFmt.getTextExtent(curPos.getFullYear().toString());
        var tmpXPos = __intervalWidth*cnt-3;
        if(tmp_metrics_obj.width > (12-curPos.getMonth())*__intervalWidth)
          tmpXPos = (__intervalWidth*cnt-3) + (((12-curPos.getMonth())*__intervalWidth)-tmp_metrics_obj.width) + 6;
	      __yearMC_array.push( __mainTimeLine_mc.createTextField('year_'+curPos.getFullYear()+"_txt",
	            __mainTimeLine_mc.getNextHighestDepth(), tmpXPos, 4,100,100) );
	      __mainTimeLine_mc['year_'+curPos.getFullYear()+"_txt"].autoSize = true;      
	      __mainTimeLine_mc['year_'+curPos.getFullYear()+"_txt"].text = curPos.getFullYear().toString()+" ";
        __mainTimeLine_mc['year_'+curPos.getFullYear()+"_txt"].setTextFormat(__yearFmt);
	    }
	    
	    //build mc for this month
	    var tmpClipName:String = "mon_"+curPos.getMonth()+"_"+curPos.getFullYear()+"_mc";
	    __mainTimeLine_mc.createEmptyMovieClip(tmpClipName,__mainTimeLine_mc.getNextHighestDepth());
    	__mainTimeLine_mc[tmpClipName]._x = __intervalWidth*cnt;
	    
	    //draw vert line
	    __mainTimeLine_mc[tmpClipName].moveTo(0,12);
  	  __mainTimeLine_mc[tmpClipName].lineStyle(1,0x999999);
  	  __mainTimeLine_mc[tmpClipName].lineTo(0,__height-12);
	  
  	  //draw center line
  	  __mainTimeLine_mc[tmpClipName].moveTo(0,Math.round(__height/2));
  	  __mainTimeLine_mc[tmpClipName].lineStyle(3,0xffffff);
  	  __mainTimeLine_mc[tmpClipName].lineTo(__intervalWidth,Math.round(__height/2));
  	  
	    //draw month
      tmp_metrics_obj = __monthFmt.getTextExtent(__monthNames_array[curPos.getMonth()]);
	    __mainTimeLine_mc[tmpClipName].createTextField('mon_'+cnt+"_txt", 
	          __mainTimeLine_mc[tmpClipName].getNextHighestDepth(),
	          0, __height-tmp_metrics_obj.height-8,100,100);
      __mainTimeLine_mc[tmpClipName]['mon_'+cnt+"_txt"].autoSize = true;
      __mainTimeLine_mc[tmpClipName]['mon_'+cnt+"_txt"].text = __monthNames_array[curPos.getMonth()]+" ";
      __mainTimeLine_mc[tmpClipName]['mon_'+cnt+"_txt"].setTextFormat(__monthFmt);
      
	    //draw indicator(s)
	    for ( var i in __pushPins_array) 
	    {
	      var pin = __pushPins_array[i];
	      if (pin.date.getFullYear() == curPos.getFullYear() && pin.date.getMonth() == curPos.getMonth()) 
	      {
	        var tmpDate = new TLDate(pin.date.getTime());
	        var tmpX = (tmpDate.getDate()/tmpDate.getActMonthDays())*__intervalWidth+__mainTimeLine_mc[tmpClipName]._x;
	        pin.virtualParent = __mainTimeLine_mc[tmpClipName];
	        pin.instance._x = tmpX;
	        pin.instance._y = Math.round(__height/2);
	      }
	    }
	    
	    //setup next interation
	    cnt++;
	    curPos.advanceMonth(1);
	  }
	  
	  
    //end loop

	}
	
	function move(pPosition:Number):Void //WOW! so much better
	{
	  //trace("moving to:"+pPosition+" from: "+__position);
	  //how many months from lineStart is new position?
	  var monFromStart = Math.floor(pPosition/__intervalWidth);
	  //whats the remainder?
	  var posRemainder = pPosition - monFromStart*__intervalWidth;
	  //whats the month size of the view?
	  var monViewSize = __viewRangeStart.compareMonth(__viewRangeEnd);
	  //set the viewport
	  __viewRangeStart.setTime(__lineRangeStart.getTime());
	  __viewRangeStart.advanceMonth(monFromStart);
	  __viewRangeEnd.setTime(__viewRangeStart.getTime());
	  __viewRangeEnd.advanceMonth(monViewSize); 
	  //draw the line
	  draw();
	  
	  //offset the line MC
	  __mainTimeLine_mc._x = -1*posRemainder;
	  
	  //fix the position
	  __position = __position+posRemainder;
	  
	  //fix the pushpins positions
	  for ( var i in __pushPins_array ) {
	    var pin = __pushPins_array[i];
      pin.instance._x = (pin.position-__position);
	  }
	  
	  //leftmost year position magic
    var tmp_metrics_obj = __yearFmt.getTextExtent(__yearMC_array[0].text);

	  if(tmp_metrics_obj.width+(Math.abs(__mainTimeLine_mc._x)-3)-10 < __yearMC_array[1]._x)
      __yearMC_array[0]._x = Math.abs(__mainTimeLine_mc._x)-3;
    else
      __yearMC_array[0]._x = __yearMC_array[1]._x-tmp_metrics_obj.width+10;
    
    //trace("now at: "+__position);
	}
	
	function moveToDate(pDate:TLDate):Void
	{
	  var months = __lineRangeStart.compareMonth(pDate);
	  var monthDist = Math.abs(__viewRangeStart.compareMonth(pDate));
	  if (months > 0 && __lineRangeEnd.compareMonth(pDate) < 0 )
	  {
  	  var newPosition = months*__intervalWidth;
  	  //trace(__position+" -> "+newPosition+" over "+Math.ceil(monthDist/2)*20+" frames")
  	  new Tween(this, "position", Elastic.easeOut, __position, newPosition, 45, false);
  	}
	}
	
	function get intervalWidth():Number
	{
	  return __intervalWidth;
	}
	
	function get position():Number
	{
	  return __position;
	}
	
	function set position(pX:Number):Void
	{
    move(pX);
	}
	
	function set moving(pMoving:Boolean):Void {
	  __moving = pMoving;
	}
	
	function get moving():Boolean {
	  return __moving;
	}
	
	function set mouseStartPosition(pPosition:Number):Void {
	  __mouseStartPosition = pPosition;
	}
	
	function get mouseStartPosition():Number {
	  return __mouseStartPosition;
	}
	
	function addPushPin(id:String, date:TLDate, symbol:String):MovieClip {
	  //lets figure out the pushpins abs position
	  var numMonths = __lineRangeStart.compareMonth(date);
	  var tmpDate = new TLDate(date.getTime())
	  var pinPosition = (numMonths * __intervalWidth) + ((tmpDate.getDate()/tmpDate.getActMonthDays())*__intervalWidth);
    
	  var i = __pushPins_array.push({id:id,date:date,symbol:symbol,position:pinPosition});
	  __pushPins_array[i-1].instance = attachMovie(symbol,"tline_pin_"+id+"_mc", getNextHighestDepth());
	  draw();
	  return __pushPins_array[i-1].instance;
	}
	
	function removePushPin(pId:String):Void {
	  for (var i in __pushPins_array) {
	    if ( __pushPins_array[i].id == pId ) {
	      __pushPins_array.splice(i,1);
	      break;
	    }
	  }
	}
}